package sqlToGUI.sqlRetrievalAlgorithms;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import java.util.GregorianCalendar;
import java.util.Properties;

import sqlToGUI.charts.helperUtilities.TelemetryDataEntry;


public abstract class AbstractDataRetrievalAlgorithm 
	implements SQLDataRetrievalAlgorithm{
	
	/**The buffer for the corresponding chart that will
	 * be updated by this algorithm */
	protected TelemetryDataEntry [] list;
	
	/**Property file holding info about how to create the database */
	protected Properties databaseInfo;
	/**Property file holding info about the tables in the database
	 * to be read from */
	protected Properties tables;
	/**Property file dealing update frequencies of the charts */
	protected Properties chartUpdateFrequency;
	
	/**variable holding the conenction to the database */
	protected Connection con;
	/**The url to connect to the database */
	protected String url;
	
	/**The string used for executing all the queries for reading data */
	protected String query;
	
	/**Statement for executing search queries in a database */
	protected Statement statement;
	/**Set containing the returned values from an executed sql statement */
	protected ResultSet rs;
	
	/**Object used for aid in getting data retrieved by timestamps */
	protected GregorianCalendar timeNow;
	/**Variable indicating at what set back time new data comes
	 * into the database to be read out from */
	protected int setBack;
	
	/**Class constructor */
	public AbstractDataRetrievalAlgorithm(){
	
		try {
			chartUpdateFrequency = new Properties();
			chartUpdateFrequency.load(new FileInputStream
					("properties/chartUpdateFrequency.properties"));
		} catch (FileNotFoundException e) {
			System.out.println("AbstractDataRetrievalAlgorithm" +
					": failed to read property file");
		} catch (IOException e) {
			System.out.println("AbstractDataRetrievalAlgorithm" +
					": failed to read property file");
		}
		
		timeNow = new GregorianCalendar();
		statement = initializeDatabaseConnection();
		setBack = Integer.parseInt(chartUpdateFrequency.
			getProperty("AlgorithmRetrievalSetBackTime"));
	}
	
	/**Register database driver, establish connection, and return the 
	 * corresponding statement object. @return a statement corresponding to 
	 * the connection. Null if the connection failed */
	public Statement initializeDatabaseConnection() {
		
		try{
			/**Initialize properties */
			databaseInfo = new Properties();
			databaseInfo.load(new FileInputStream
					("properties/databaseInfo.properties"));
			tables = new Properties();
			tables.load(new FileInputStream
					("properties/tables.properties"));

		}catch (FileNotFoundException e){
			e.printStackTrace();
			System.err.print("\nData retrieval algorithm: Properties file" +
					"for reading database + " +
			"not found\n");
		}catch (IOException e){
			e.printStackTrace();
			System.err.print("\nData retrieval algorithm: Properties file " + 
					"for reading database not found\n");
		}

		try {
			/**Register the driver class */
			Class.forName(databaseInfo.getProperty("DatabaseDriverClass"));
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
			System.err.println("Data retrieval algorithm: You need to " +
					"install the specified database " +
					"driver before running this software.");
			System.exit(1);
		}

		/**For example, url looks like "jdbc:mysql://localhost:3306/mysql" */

		try {
			/**Try to connect to the database using the provided information 
			 * With the schema set to what is provided. Let's say it's 
			 * "bluesky" */
			url = "jdbc:mysql://"+databaseInfo.getProperty("DatabaseAddress")
			+":"+databaseInfo.getProperty("DatabasePort")+"/"+
			databaseInfo.getProperty("Schema");
			con = (Connection) DriverManager.getConnection(url,
					databaseInfo.getProperty("User"), 
					databaseInfo.getProperty("Password"));
		} catch (SQLException e) {
			
			/**If the connection failed, than try to connect without a default 
			 * schema */
			System.out.println("Data retrieval algorithm: Database: " + 
					databaseInfo.getProperty("Schema") + 
			" does not exist.\nCreating new scheme...");
			url = "jdbc:mysql://"+databaseInfo.getProperty("DatabaseAddress")
			+":"+databaseInfo.getProperty("DatabasePort");
			
			try{
				con = (Connection) DriverManager.getConnection(url,
						databaseInfo.getProperty("User"), 
						databaseInfo.getProperty("Password"));
			}catch (SQLException d){
				/**Now it really goes wrong. Exit the system */
				d.printStackTrace();
				return null;
			}
		}
		
		System.out.println("Data retrieval algorithm: Database Connection " +
				"for reading data established.");
		System.out.println("URL: " + url);
		System.out.println("Connection: " + con);
		
		/**Try to initialize the statement */
		try {
			return (Statement) con.createStatement();
		} catch (SQLException e) {
			System.out.println("Data retrieval algorithm: Failed to" +
					"make database connection");
			return null;
		}
		
	}
}
